from .builder import Builder



class Node(object):
    def toposort(self):
        order = []
        _toposort_rec(self, order, set())
        return order


def _toposort_rec(node, order, visited):
    visited.add(node)
    for child in node.children:
        if child not in visited:
            _toposort_rec(child, order, visited)
    order.append(node)


class Namespace(object):
    """an object that provides nested namespaces to modules"""
    __slots__ = ["__parent__", "__locals__"]
    
    def __init__(self, parent = None):
        object.__setattr__(self, "__parent__", parent)
        object.__setattr__(self, "__locals__", {})
    def __repr__(self):
        items = ", ".join("%s = %r" % (n, v) for n, v in self)
        return "<Namespace: %s>" % (items,)
    def __contains__(self, name):
        return self[name] is not None
    def __dir__(self):
        names = set()
        curr = self
        while curr is not None:
            for k, v in object.__getattribute__(curr, "__locals__"):
                if v is not None:
                    names[k] = v
            curr = object.__getattribute__(curr, "__parent__")
        return list(names)
    def __nonzero__(self):
        return bool(Namespace.__dir__(self))
    def __iter__(self):
        for name in Namespace.__dir__(self):
            yield name, self[name]
    def __copy__(self):
        ns = Namespace()
        for name, value in self:
            ns[name] = value
        return ns
    def __delattr__(self, name):
        self[name] = None
    def __getattribute__(self, name):
        value = object.__getattribute__(self, "__locals__").get(name, AttributeError)
        if value is AttributeError:
            parent = object.__getattribute__(self, "__parent__")
            if parent is None:
                value = None
            else:
                value = getattr(parent, name)
        return value
    def __setattr__(self, name, value):
        object.__getattribute__(self, "__locals__")[name] = value
    __getitem__ = __getattribute__
    __delitem__ = __delattr__
    __setitem__ = __setattr__






